package com.ly.jvm.oom.memoryleak.threadlocal;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;


import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Classname Service
 * @Description TODO
 * @Date 2020/12/28 20:55
 * @Author 冷心影翼
 */
public class ThreadLocalWithPoolMemoryLeak {

    static ThreadPoolExecutor threadPoolExecutor;

    ThreadLocal<User> threadLocal = new ThreadLocal<>();

	public ThreadLocalWithPoolMemoryLeak(){
		threadPoolExecutor  = new ThreadPoolExecutor(
			Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(),
			10, TimeUnit.SECONDS,
			new LinkedBlockingQueue<>(100),
			Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
	}

	public void setUser() {
	    //10M
		threadLocal.set(new User(Thread.currentThread().getId()+"",new byte[1024*1024*10]));
	}

	public void serviceA()  {
	    //100M
        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.execute(() ->{
                setUser();
                ServiceB(threadLocal.get());
//                threadLocal.remove();
            });
        }
        try {
            TimeUnit.SECONDS.sleep(60);
            threadLocal = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

	}


	public void ServiceB(User u) {
		try {
            System.out.println(u);
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class T {

    public static void main(String[] args)  {
        ThreadLocalWithPoolMemoryLeak threadLocalWithPoolMemoryLeak = new ThreadLocalWithPoolMemoryLeak();
        threadLocalWithPoolMemoryLeak.serviceA();

        ThreadLocalWithPoolMemoryLeak.threadPoolExecutor.shutdown();
        while (true) {

        }
    }
}


//https://blog.csdn.net/liubenlong007/article/details/107048843
//https://www.cnblogs.com/westlin/p/10645217.html


@Setter
@AllArgsConstructor
class User {

	String id;
    byte[] data;

    @Override
    public String toString() {
        return "User{" +
            "id=" + id +
            '}';
    }
}